package com.yan.design.util;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.NumberFormat;

/**
 * BigDecimal 工具类
 * @author shengren.yan
 * @create 2022-07-12
 */
public class DecimalUtils {

    // 保留两位小数
    public static final int MONEY_POINT = 2;
    // 货币格式化
    private static final NumberFormat CURRENCY = NumberFormat.getCurrencyInstance();
    // 百分比格式化
    private static final NumberFormat PERCENT = NumberFormat.getPercentInstance();
    // 万元
    private static final BigDecimal MILLION = new BigDecimal(100 * 100);
    // 亿
    private static final BigDecimal BILLION = new BigDecimal(100 * 100 * 100 * 100);
    // 百
    private static final BigDecimal HUNDRED = new BigDecimal(100);
    // 千
    private static final BigDecimal THOUSAND = new BigDecimal(100 * 10);

    /**
     * 转为字符串(防止返回可续计数法表达式)
     *
     * @param x 要转字符串的小数
     * @return String
     */
    public static String toPlainString(BigDecimal x) {
        if (x == null) {
            return "0";
        }
        return x.stripTrailingZeros().toPlainString();
    }

    /**
     * 去除 - 可续计数法表达式
     *
     * @param num 要转字符串的小数
     * @return BigDecimal
     */
    public static BigDecimal removeSstripTZ(BigDecimal num) {
        num = null == num ? new BigDecimal(BigInteger.ZERO) : num;
        return new BigDecimal(num.stripTrailingZeros().toPlainString());
    }


    /**
     * 判断 n1是否小于n2
     *
     * @param n2 如果 n2 是 null 是 0
     * @return n1小于n2返回 true
     */
    public static boolean lt(BigDecimal n1, BigDecimal n2 ) {
        n2 = null == n2 ? new BigDecimal(BigInteger.ZERO) : n2;
        return n1.compareTo(n2) < 0;
    }

    /**
     * 判断 n1是否小于等于n2
     *
     * @param n2 如果 n2 是 null 是 0
     * @return n1小于或者等于n2返回 true
     */
    public static boolean lte(BigDecimal n1, BigDecimal n2) {
        n2 = null == n2 ? new BigDecimal(BigInteger.ZERO) : n2;
        return (n1.compareTo(n2) < 0) || (n1.compareTo(n2) == 0);
    }

    /**
     * 判断 n1是否大于n2
     *
     * @param n2 如果 n2 是 null 是 0
     * @return n1大于n2返回 true
     */
    public static boolean gt(BigDecimal n1, BigDecimal n2) {
        n2 = null == n2 ? new BigDecimal(BigInteger.ZERO) : n2;
        return n1.compareTo(n2) > 0;
    }

    /**
     * 判断 n1是否大于等于n2
     *
     * @param n2 如果 n2 是 null 是 0
     * @return num1大于或者等于num2返回true
     */
    public static boolean gte(BigDecimal n1, BigDecimal n2) {
        n2 = null == n2 ? new BigDecimal(BigInteger.ZERO) : n2;
        return (n1.compareTo(n2) > 0) || (n1.compareTo(n2) == 0);
    }

    /**
     * 判断 n1是否等于n2
     *
     * @param n2 如果 n2 是 null 是 0
     * @return n1等于n2返回 true
     */
    public static boolean eq(BigDecimal n1, BigDecimal n2) {
        n2 = null == n2 ? new BigDecimal(BigInteger.ZERO) : n2;
        return n1.compareTo(n2) == 0;
    }

    /**
     * BigDecimal货币格式化
     * @return String
     */
    public static String currencyFormat(BigDecimal num) {
        return CURRENCY.format(num);
    }

    /**
     * BigDecimal百分比格式化
     * @return String
     */
    public static String rateFormat(BigDecimal num) {
        return PERCENT.format(num);
    }

    /**
     * 格式化-带千位符
     * @return String
     */
    public static String moneyFormat(BigDecimal num) {
        StringBuilder str = new StringBuilder();
        str.append(toPlainString(num));
        int index = str.indexOf(".");
        //循环插入','
        while((index -= 3) > 0) {
            str.insert(index, ",");
        }
        return str.toString();
    }

    /**
     * 加法
     */
    public static BigDecimal add(BigDecimal n1, BigDecimal n2) {
        return n1.add(n2);
    }

    /**
     * 减法
     */
    public static BigDecimal sub(BigDecimal n1, BigDecimal n2) {
        return n1.subtract(n2);
    }

    /**
     * 乘法
     */
    public static BigDecimal multiply(BigDecimal n1, BigDecimal n2) {
        return n1.multiply(n2);
    }

    /**
     * 除法 (除法除不尽会抛异常)
     */
    public static BigDecimal divide(BigDecimal n1, BigDecimal n2) {
        return n1.divide(n2);
    }


    /**
     * 除法 (默认：四舍五入)
     * @param scale 保留几位小数
     */
    public static BigDecimal divide(BigDecimal n1, BigDecimal n2, int scale) {
        scale = scale < 0 ? MONEY_POINT : scale;
        return n1.divide(n2, scale, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 除法 (不进行四舍五入)
     * @param scale 保留几位小数
     */
    public static BigDecimal divideRoundDown(BigDecimal n1, BigDecimal n2, int scale) {
        scale = scale < 0 ? MONEY_POINT : scale;
        return n1.divide(n2, scale, BigDecimal.ROUND_DOWN);
    }


    /**
     * 类型转换 (Float)
     *
     * @return float
     */
    public static float toFloat(BigDecimal num) {
        return num.floatValue();
    }

    /**
     * 类型转换 (int)
     *
     * @return int
     */
    public static int toInt(BigDecimal num) {
        return num.intValue();
    }


    /**
     * 类型转换 (double)
     *
     * @return double
     */
    public static double toDouble(BigDecimal num) {
        return num.doubleValue();
    }



    /**
     * 转换为万元
     *
     * @param num 要转字符串的小数
     * @return 转换为的小数
     */
    public static BigDecimal toMILLION(BigDecimal num) {
        num = null == num ? new BigDecimal(BigInteger.ZERO) : num;
        return removeSstripTZ(divide(num, MILLION, MONEY_POINT));
    }
    // 转换为万元 - 参数1：要转字符串的小数  参数2：down 为true-不进行四舍五入
    public static BigDecimal toMILLION(BigDecimal num , Boolean down) {
        num = null == num ? new BigDecimal(BigInteger.ZERO) : num;
        if (down){
            return removeSstripTZ(divideRoundDown(num, MILLION, MONEY_POINT));
        }else {
            return removeSstripTZ(divide(num, MILLION, MONEY_POINT));
        }
    }

    /**
     * 转换为亿元
     *
     * @param num 要转字符串的小数
     * @return 转换为的小数
     */
    public static BigDecimal toBILLION(BigDecimal num) {
        num = null == num ? new BigDecimal(BigInteger.ZERO) : num;
        return removeSstripTZ(divide(num, BILLION, MONEY_POINT));
    }
    // 转换为亿元 - 参数1：要转字符串的小数  参数2：down 为true-不进行四舍五入
    public static BigDecimal toBILLION(BigDecimal num , Boolean down) {
        num = null == num ? new BigDecimal(BigInteger.ZERO) : num;
        if (down){
            return removeSstripTZ(divideRoundDown(num, BILLION, MONEY_POINT));
        }else {
            return removeSstripTZ(divide(num, BILLION, MONEY_POINT));
        }
    }

    /**
     * 转换为亿千
     *
     * @param num 要转字符串的小数
     * @return 转换为的小数
     */
    public static BigDecimal toTHOUSAND(BigDecimal num) {
        num = null == num ? new BigDecimal(BigInteger.ZERO) : num;
        return removeSstripTZ(divide(num, THOUSAND, MONEY_POINT));
    }
    // 转换为亿千 - 参数1：要转字符串的小数  参数2：down 为true-不进行四舍五入
    public static BigDecimal toTHOUSAND(BigDecimal num , Boolean down) {
        num = null == num ? new BigDecimal(BigInteger.ZERO) : num;
        if (down){
            return removeSstripTZ(divideRoundDown(num, THOUSAND, MONEY_POINT));
        }else {
            return removeSstripTZ(divide(num, THOUSAND, MONEY_POINT));
        }
    }


    /**
     * BigDecimal 求占比
     * @param n1  数值1
     * @param n2  数值2
     * @return 占比 （已乘100）
     */
    public static BigDecimal rateFormatNum(BigDecimal n1,BigDecimal n2){
        n1 = null == n1 ? new BigDecimal(BigInteger.ZERO) : n1;
        n2 = null == n2 ? new BigDecimal(BigInteger.ZERO) : n2;
        if (eq(n2, BigDecimal.ZERO)) {
            return BigDecimal.ZERO;
        }
        return  divide(multiply(n1, HUNDRED), n2,MONEY_POINT);
    }

    /**
     * BigDecimal 求占比
     * @param n1  数值1
     * @param n2  数值2
     * @return 占比 （不乘100）
     */
    public static BigDecimal rateFormatNum2(BigDecimal n1,BigDecimal n2){
        n1 = null == n1 ? new BigDecimal(BigInteger.ZERO) : n1;
        n2 = null == n2 ? new BigDecimal(BigInteger.ZERO) : n2;
        if (eq(n2, BigDecimal.ZERO)) {
            return BigDecimal.ZERO;
        }
        return  divide(n1, n2,MONEY_POINT);
    }


    public static void main(String[] args) {
        BigDecimal n1 = new BigDecimal("10");
        BigDecimal n2 = new BigDecimal("122");
//        BigDecimal s = rateFormatNum(n1,n2);

        BigDecimal s = rateFormatNum2(n1,n2);
        System.out.println(s);
    }

}
